﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using FieldLib;
using FieldLib.Comm;
using FieldDevice.ModBus;
namespace FieldDevice
{
    public abstract class Device : DeviceBase, IDevice, IChannel
    {
        public string DeviceName
        {
            get{ return base.Label; }
            set { base.Label = value; }
        }
        public string CommPortName { get; set; }
        public string DeviceModel { get; set; }
        public string Description { get; set; }
        public uint NCPAddress
        {
            get { return (uint)base.Id; }
            set { base.Id = (int)value; }
        }
        public string NCPAddressHex { get { return this.NCPAddress.ToString("X"); } }
        public string IPAddress { get; set; }
        public byte ModbusAddress { get; set; }
        public Device.DeviceConfigBase Config
        {
            get { return this.GetDeviceConfig(); }
            set
            {
                this.SetDeviceConfig((Device.DeviceConfigBase)value);
            }
        }

        public  List<ModBusPacket> requests = new List<ModBusPacket>();
        public List<ModBusPacket> Requests { get { return this.requests; } }
        protected virtual void RequestRegister(ushort registeraddress, ushort datanumber)
        {
            ModBusPacket modframe = new ModBusPacket();
            modframe.Function = this.ModBusReadCommand;
            modframe.SlaveAddress = (byte)this.ModbusAddress;

            modframe.DataAddressHi = (byte)(registeraddress >> 8);
            modframe.DataAddressLow = (byte)(registeraddress & 0x00FF);
            modframe.DataNumberHi = 0;
            modframe.DataNumberLow = (byte)(datanumber & 0x00FF);
            this.requests.Add(modframe);
        }

        object IDevice.Config { 
            get { 
                return this.GetDeviceConfig();
            } 
            set { 
                this.SetDeviceConfig((DeviceConfigBase)value);
            } 
        }
        public SerialPort SerialPort { get; set; }
        public enum DeviceCategory
        {
            PowerMeter,
            DCDevice,
            HighVoltageDevice,
            Temperature,
            EmaxE3,
            REF615,
        }
        public DeviceCategory Category;

        /// <summary>
        /// 表示数据是否以改变
        /// </summary>
        public bool Dirty { get; set; }
        string IDevice.DeviceCategory { get { return Category.ToString(); } }
        public Device(DeviceCategory categrogy, byte address, string name)
            :this(categrogy, address)
        {
            this.DeviceName = name;
        }
        public Device(DeviceCategory categrogy, byte address)
        {
            this.Category = categrogy;
            this.ModbusAddress = address;
            switch (this.Category)
            {
                case DeviceCategory.HighVoltageDevice:
                    this.InitHighVoltageDevice();
                    break;
                case DeviceCategory.PowerMeter:
                    this.InitPowerMeterDevice();
                    break;
                case DeviceCategory.DCDevice:
                    this.InitDCDevice();
                    break;
                case DeviceCategory.Temperature:
                    this.InitTemperature();
                    break;
                case DeviceCategory.EmaxE3:
                    this.InitEmaxE3();
                    break;
                default:
                    break;
            }
        }

        protected void EnrollRead(string read)
        {
            CurrentReads.Add(read, 0);
            DataQueues.Add(read, new DataQueue());
        }

        void InitREF615()
        {
            string[] values = new string[]{
                "IA",
                "IB",
                "IC",
                "OverCurrentProtect","ZeroFlowProtect","QuickBreak","OvertemperatureTrip",
                "Iso_Knife_Cutoff","Iso_Knife_Connect",
                "GroundedKnifeCutoff","GroundedKnifeConnect",
                "CB_Cutoff","CB_Connect",
                "Transformer_HighTemp",
                "Transformer_OvereTemp",
                "PressureAnomaly","Vol_Tran_IsolationKnife_Connect ","LoadSwitch_Connect","CBEnergyStored",
            };
            foreach(string value in values)
            {
                 EnrollRead(value);
            }
        }

        void InitHighVoltageDevice()
        {
            string[] values = new string[]{
                "VA",
                "VB",
                "VC",
                "IA",
                "IB",
                "IC",
                "Vab",
                "Vbc",
                "Vca" ,
                "P","Q","S","PF","EPI","EQL","H1_YX1","Handcart_Position","OperationCondition_Work",
                "OperationCondition_Stop","H1_YX5","Grouding_Switch","H1_YX7","H1_YX8","FR","Ratio",
              };
            foreach (string value in values)
                EnrollRead(value);
           
        }
        public const string OnOffValueName = "DI1";
        void InitPowerMeterDevice()                 //初始化低压仪表的参数
        {
            string[] values = new string[]{
                "VA","VB","VC",
                "IA","IB","IC",
                "Vab","Vbc","Vca",
                "P",//有功功率
                "Q",//无功功率
                "S",//视在功率
                "FR",//频率
                "PF",//功率因素
                "EPI","EQL",
                "Ratio",//互感线圈比率
            };


            foreach (string v in values)
            {
                CurrentReads.Add(v, 0);
                DataQueues.Add(v, new DataQueue());
            }

            string[] booleanvalues = new string[]{
                OnOffValueName,
            };
            foreach (string v in booleanvalues)
            {
                this.CurrentBooleanReads.Add(v, null);
            }
        }
        void InitEmaxE3()
        {
            string[] values = new string[]{
             "VA","VB","VC",
                "IA","IB","IC",
                "Vab","Vbc","Vca","DI1","Ratio",
                "P","Q","S","FR","PF", "EPI","EQL","CB_Tripp","CB_Connected","CB_Open"};
            foreach (string value in values)
                EnrollRead(value);
        }

        /// <summary>
        /// 电路开路闭路状态
        /// 1: On表示闭路
        /// 0: Off表示开路
        /// </summary>
        public bool OnOff
        {
            get
            {
                return this.CurrentBooleanReads[OnOffValueName]==true;
            }
        }

      protected void InitDCDevice()
        {
            string[] values = new string[] 
            {"1#","2#","3#","4#","5#","6#","7#","8#","9#",
             "ZLP_UAB","ZLP_UBC" ,"ZLP_UCA","ZLP_U0","ZLP_Ubat","ZLP_UKM","ZLP_UCD","ZLP_IKM","ZLP_IFD",
             "ZLP_Alaram_1","ZLP_Alaram_2","ZLP_Alaram_3","ZLP_Alaram_4","ZLP_Alaram_5",
             "ZLP_Alaram_6","ZLP_Alaram_7","ZLP_Alaram_8","ZLP_Alaram_9","ZLP_Alaram_10","ZLP_Alaram_11",
             "ZLP_Alaram_12","ZLP_Alaram_13","ZLP_Alaram_14","ZLP_Alaram_15","ZLP_Alaram_16","ZLP_Alaram_17" 
             ,"ZLP_Alaram_18"  ,"ZLP_Alaram_19","ZLP_Alaram_20","ZLP_Alaram_21","ZLP_Alaram_22","ZLP_Alaram_23",
             "ZLP_Alaram_24","ZLP_Alaram_25",  
          };
            foreach (string v in values)
            {
                CurrentReads.Add(v, 0);
                DataQueues.Add(v, new DataQueue());
            }

        }                   //初始化直流屏的参数

      protected void InitTemperature()                  //初始化温度参数
      {
          string[] values = new string[]
        {
           "Temper_A","Temper_B","Temper_C","Temper_D","Fault_Alarm"
           ,"Slug_OverTemperature","OverTemperature_Alarm",
           "OverTemperature_Trip","WM_Control"
        };
          foreach (string v in values)
          {
              CurrentReads.Add(v, 0);
              DataQueues.Add(v, new DataQueue());
          }
      }

        public SortedList<string, bool?> CurrentBooleanReads = new SortedList<string, bool?>();

        /// <summary>
        /// 按名字的各数值点
        /// Key: string 测量的名字
        /// Value: float测量的值
        /// </summary>
        public SortedList<string, float> CurrentReads = new SortedList<string, float>();

        public SortedList<string, DataQueue> DataQueues = new SortedList<string, DataQueue>();
        public SortedList<ushort, ushort> Registers = new SortedList<ushort, ushort>();

        public PowerQueue PowerQueues = new PowerQueue();
        public void RecordRead(string name, float value)
        {
            CurrentRoundReads[name] = value;
            CurrentReads[name] = value;
            DataQueue.DataItem item = new DataQueue.DataItem(value);
            this.DataQueues[name].Add(item);
            base.EvaluateFloatValue(name, value);
            if(FieldLib.SystemConfig.GlobalSystemConfig.EnableLogReads)
                DeviceManager.GlobalDeviceManager.FieldReadLog.LogRead((int)this.NCPAddress, 
                    this.DeviceModel, name, value, this.CurrentReadTime);
        }


        public void RecordBooleanRead(string name, bool value)
        {
            bool? prev = this.CurrentBooleanReads[name];
            this.CurrentBooleanReads[name] = value;
            switch (name)
            {
                case OnOffValueName:
                    string text=value?"合闸":"开闸";
                    if (prev != value)
                    {
                        if (prev == null)
                            this.FireFieldEvent("初次读取开关状态：" + text, null);
                        else
                        {
                            string prevtext = prev == true ? "合闸" : "开闸";
                            this.FireFieldEvent("开关状态改变：" + prevtext + "=>" + text, null);
                        }
                    }
                    break;
            }
        }
         public DataQueue GetDataQueue(string name)
        {
            return this.DataQueues[name];
        }


        public delegate void ReadChangeEventHander(Device device, string name, float value);
        public event ReadChangeEventHander ReadChangeEvent;

        public void FireReadChangeEvent()
        {
            if (this.ReadChangeEvent != null)
                this.ReadChangeEvent(this, null, 0);
        }

        //public ushort ReadDevice(ModBusPacket AddressCurrentARegister)
        //{
        //    ushort current=(ushort)ReadRegister(AddressCurrentARegister);
        //    return current;
        //}

        /// <summary>
        /// 默认情形下,ModBus读寄存器命令为03。但有的设备(如REF542Plus)用04，
        /// 此时继承的设备类重载此函数，改写命令
        /// </summary>
        protected virtual byte ModBusReadCommand
        {
            get { return ModBusFunction.READHOLDINGREGISTER; }
        }
        public byte[] ReadRegister(ushort registeraddress, ushort datanumber)
        {
            ModBusPacket modframe = new ModBusPacket();
            modframe.Function = this.ModBusReadCommand;
            modframe.SlaveAddress = (byte)this.ModbusAddress;

            modframe.DataAddressHi = (byte)(registeraddress>>8);
            modframe.DataAddressLow = (byte)(registeraddress&0x00FF);
            modframe.DataNumberHi = 0;
            modframe.DataNumberLow = (byte)(datanumber&0x00FF);
            byte[] resultbytes = this.ReadRegister(modframe);
            return resultbytes;
        }
        public void ReadAndUpdateValue(ushort DataAddr, ushort DataNumber)
        {
            ModBusPacket packet = new ModBusPacket();
            packet.SlaveAddress = this.ModbusAddress;
            packet.Function = FieldDevice.ModBus.ModBusFunction.READHOLDINGREGISTER;
            packet.DataAddressHi = (byte)(DataAddr >> 8);
            packet.DataAddressLow = (byte)(DataAddr & 0xff);
            packet.DataNumberHi = (byte)(DataNumber >> 8);
            packet.DataNumberLow = (byte)(DataNumber & 0xff);
            DeviceManager.GlobalDeviceManager.ModBusIO.Send(this, packet);
            byte[] RegistersValue = DeviceManager.GlobalDeviceManager.ModBusIO.Receive(this);
            TranslateRegister(packet, RegistersValue);
        }

        public Exception CurrentException;
        DateTime CurrentReadTime;
        void IDevice.OnModbusPacketResponse(ModBusPacket request, byte[] response)
        {
            this.CurrentReadTime = DateTime.Now;
            lock (this)//陆续会有包上来，必须避免多重中断
            {
                try
                {
                    if (response[0] != this.ModbusAddress)
                        throw new Exception("Radiculous!");
                    this.Counter.RespodesCounter++;
                    for (ushort u = 0; u < request.DataNumber; u++)
                    {
                        ushort add = (ushort)(request.DataAddress + u);
                        int begin = 3 + u * 2;
                        this.Registers[add] = FieldLib.Utility.BytesToUShort(response[begin], response[begin + 1]);
                    }
                    this.TranslateRegister(request, response);
                    this.Dirty = true;
                    foreach (ICommWatch watch in this.Watchs)
                    {
                        watch.Watch(CommDirection.In, response);
                    }
                }
                catch (Exception exp)
                {
                    this.CurrentException = exp;
                    ExceptionHandler.OnException(this, exp);
                }
                if(SystemConfig.GlobalSystemConfig.ScheduleManner!= SystemConfig.EnumScheduleManner.OnTimer)
                    this.FireReadChangeEvent(null, 0.0f);
            }
        }

        void IDevice.OnModbusPacketSent(ModBusPacket request)
        {
            foreach (ICommWatch watch in this.Watchs)
            {
                watch.Watch(CommDirection.Out, request.ToBytes());
            }
        }
        public byte[] ReadRegister(ModBusPacket Registers)
        {
            if (DeviceManager.GlobalDeviceManager.ModBusIO.IsEmulation)
            {
                DeviceManager.GlobalDeviceManager.ModBusIO.Send(this, Registers);
                this.buffercount = 0;           //reset receiving buffer
                byte[] resultbytes = DeviceManager.GlobalDeviceManager.ModBusIO.Receive(this);
                return resultbytes;
            }
            else
            {
                return this.SerialPort.ReadRegister(Registers, 0x00010101, this.NCPAddress);
            }
        }

        public void UpdateReads(FieldLib.UpdateSync sync)
        {
        }
        public virtual void DebugReads()
        {
            this.SerialPort.UpdateDevice(this);
        }

        protected Font font = new Font(FontFamily.GenericSansSerif, 10.0f);

        /// <summary>
        /// 在监控画面上描绘测量参数
        /// </summary>
        /// <param name="g"></param>
        /// <param name="pen"></param>
        /// <param name="isSelected"></param>
        /// <param name="zoom">缩放比例</param>
        /// <param name="offset">位置偏移</param>
        public virtual void Draw(System.Drawing.Graphics g, System.Drawing.Pen pen, bool isSelected, System.Drawing.SizeF zoom, Point offset)
        {
            SolidBrush brush = new SolidBrush(pen.Color);
            Point p = offset;
            string vFormat = "F1";
            float vRatio = 1.0f;
            string vUnit = "V";

            int space = 18;
            brush.Color = Color.Yellow;
            g.DrawString("Ia:" + this.CurrentReads["IA"].ToString("F2") + "A", font, brush, p.X, p.Y);
            brush.Color = Color.Green;
            g.DrawString("Ib:" + this.CurrentReads["IB"].ToString("F2") + "A", font, brush, p.X, p.Y + space);
            brush.Color = Color.Red;
            g.DrawString("Ic:" + this.CurrentReads["IC"].ToString("F2") + "A", font, brush, p.X, p.Y + space + space);

            if (this.GetDeviceConfig().DisplayCategory == DeviceConfigBase.EnumDisplayCategory.HighVoltageDevice)
            {
                vFormat = "F2";
                vRatio = 1000.0f;
                vUnit = "kV";
                brush.Color = Color.Yellow;
                g.DrawString("Vab:" + (this.CurrentReads["Vab"] / vRatio).ToString(vFormat) + vUnit, font, brush, p.X + 65, p.Y);
                brush.Color = Color.Green;
                g.DrawString("Vbc:" + (this.CurrentReads["Vbc"] / vRatio).ToString(vFormat) + vUnit, font, brush, p.X + 65, p.Y + space);
                brush.Color = Color.Red;
                g.DrawString("Vca:" + (this.CurrentReads["Vca"] / vRatio).ToString(vFormat) + vUnit, font, brush, p.X + 65, p.Y + space + space);
            }
            else if (this.GetDeviceConfig().DisplayCategory == DeviceConfigBase.EnumDisplayCategory.PowerMeter)
            {
                vFormat = "F1";
                vRatio = 1.0f;
                vUnit = "V";
                brush.Color = Color.Yellow;
                g.DrawString("Va:" + (this.CurrentReads["VA"] / vRatio).ToString(vFormat) + vUnit, font, brush, p.X + 65, p.Y);
                brush.Color = Color.Green;
                g.DrawString("Vb:" + (this.CurrentReads["VB"] / vRatio).ToString(vFormat) + vUnit, font, brush, p.X + 65, p.Y + space);
                brush.Color = Color.Red;
                g.DrawString("Vc:" + (this.CurrentReads["VC"] / vRatio).ToString(vFormat) + vUnit, font, brush, p.X + 65, p.Y + space + space);
            }
            else if (this.GetType() == typeof(Devices.DeviceACR330ELH) ||
                this.GetType() == typeof(Devices.DevicePM5350) ||
                this.GetType() == typeof(Devices.DevicePMC43M))
            {
                vFormat = "F1";
                vRatio = 1.0f;
                vUnit = "V";
                brush.Color = Color.Yellow;
                g.DrawString("Vab:" + (this.CurrentReads["Vab"] / vRatio).ToString(vFormat) + vUnit, font, brush, p.X + 65, p.Y);
                brush.Color = Color.Green;
                g.DrawString("Vbc:" + (this.CurrentReads["Vbc"] / vRatio).ToString(vFormat) + vUnit, font, brush, p.X + 65, p.Y + space);
                brush.Color = Color.Red;
                g.DrawString("Vca:" + (this.CurrentReads["Vca"] / vRatio).ToString(vFormat) + vUnit, font, brush, p.X + 65, p.Y + space + space);
            }
        }

        protected void FireReadChangeEvent(string valname, float value)
        {
            if (this.ReadChangeEvent != null)
                this.ReadChangeEvent(this, valname, value);
        }
        protected void UpdateRead(string name, ushort registeraddress)
        {
        }

        #region
        public SortedList<string, float> CurrentRoundReads = new SortedList<string, float>();
        public virtual void TranslateRegister(ModBusPacket request, byte[] response/*, ushort DataAddr*/ )
        {
            CurrentRoundReads.Clear();
            CheckOut(response);
            byte datalength = response[2];
            int DataNumber = datalength / 2;
            for (int i = 0; i < DataNumber; i++)
            {
                Translate(response, 3 + i * 2, (ushort)(request.DataAddress + i));
            }

            if (((this is Devices.DeviceACR120EL) && request.DataAddress == Emulation.ACR120ELEmulator.ADDR_DIO) ||
                ((this is Devices.DeviceACR330ELH) && request.DataAddress == Emulation.ACR330ELHEmulator.ADDR_DI1))
                recordPower(request.ToBytes(), response);
        }
        #endregion



        DateTime PreviousRecordTime;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="now"></param>
        /// <returns></returns>
        bool TimePassed(DateTime now)
        {
            if (this.Counter.PowerRecordsCounter == 0)
            {//启动时自动记录一次
                this.Counter.PowerRecordsCounter++;
                PreviousRecordTime = now;
                return true;
            }
            else
            {
                switch (FieldLib.SystemConfig.GlobalSystemConfig.EcoSysConfig.ReadPowerIntervalUnit)
                {
                    case EcoSysConfig.EnumReadPowerIntervalUnit.Hour:
                        {
                            int hour = ((now.Hour + 24) - PreviousRecordTime.Hour) % 24;//自上次读数后的小时数
                            if (hour >= FieldLib.SystemConfig.GlobalSystemConfig.EcoSysConfig.ReadPowerIntervalNumber)
                            {//每1小时读数一次
                                this.Counter.PowerRecordsCounter++;
                                return true;
                            }
                        }
                        break;
                    case EcoSysConfig.EnumReadPowerIntervalUnit.Minute:
                        {
                            int minutes = ((now.Minute + 60) - PreviousRecordTime.Minute) % 60;
                            if (minutes >= 5)
                            {//每5分钟读数一次
                                this.Counter.PowerRecordsCounter++;
                                return true;
                            }
                            break;
                        }
                    default:
                        throw new NotImplementedException();
                }
                return false;
            }

        }

        PowerQueue.PowerItem PreviousPowerItem;
        /// <summary>
        /// 记录功率、电能读书到数据库
        /// </summary>
        void recordPower(byte[] request, byte[] response)
        {
            DateTime now = DateTime.Now;
            if (!TimePassed(now))
                return;
            PowerQueue.PowerItem newitem = this.PowerQueues.RecordPowerItem(now, CurrentReads["EPI"], CurrentReads["EQL"], CurrentReads["PF"], request, response);
            if (PreviousPowerItem != null)
            {
                newitem.PComsuption = newitem.PP - PreviousPowerItem.PP;
                newitem.QComsuption = newitem.QP - PreviousPowerItem.QP;
                newitem.TimeSpan = newitem.Time - PreviousPowerItem.Time;
            }
            newitem.PP = CurrentReads["EPI"];//有功电度读数
            newitem.PF = CurrentReads["PF"];
            newitem.QP = CurrentReads["EQL"];//无功电度读数
            this.PreviousRecordTime = now;
            Power.PowerStorage.StaticPowerStorage.RecordPowerReads(this, newitem);
            this.PreviousPowerItem = newitem;
        }
        
        protected bool CheckReceiveModbusPacket(byte[] value, ushort DataNumber, out string wrongmessage)
        {
            if (value.Length <= 3)                       //判断通信得到的数据是否小于三个
                throw new Exception("Datas Wrong");
            byte modbus_address = value[0];
            if ((ushort)modbus_address != this.ModbusAddress)
                throw new Exception("address problem");

            if (value.Length != value[2] + 5)       //判断返回的数据是否完整
                //    throw new Exception("Data Wrong");
                throw new Exception("Data length wrong!");
            //if ((int)value[2] != (int)(DataNumber * 2))
            //    throw new Exception("Data length is not expected!");
            wrongmessage = null;
            return true;
        }

        protected abstract float Translate(byte[] value, int begin, ushort registeraddress);

        ushort[] CommonRegisterAddresses = new ushort[]{
            
        };

        byte[] buffer = new byte[512];//用于缓存被拆散的ModBus包
        int buffercount = 0;

        /// <summary>
        /// 一个ModBusPacket可能被分作几个串口字节数组回发，从而作为多个IP包发送回来。
        /// 这里从新组装这些包
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="packet"></param>
        /// <returns></returns>
        public bool IsPacketFinished(byte[] bytes, out byte[] packet)
        {
            packet=null;
            for (int i = 0; i < bytes.Length; i++)
            {
                buffer[buffercount] = bytes[i];
                buffercount++;
            }
            int exepected = buffer[2]+5;
            if (buffercount < exepected)
                return false;
            else if (buffercount == exepected)
            {
                packet = new byte[this.buffercount];
                for (int j = 0; j < this.buffercount; j++)
                    packet[j] = buffer[j];
                this.buffercount = 0;
                return true;
            }
            else
            {
                throw new Exception("Unexpected");
            }
        }


        /// <summary>
        /// CheckOut 检验返回来的数据是否正确
        /// </summary>
        /// <param name="value"></param>
        public static void CheckOut(byte[] value)       
        {
            if (value.Length <= 3)                       //判断通信得到的数据是否小于三个
            {
                //   throw new Exception("Datas Wrong");
                return;
            }
            else
            {
                if (value.Length != value[2] + 5)       //判断返回的数据是否完整
                    //    throw new Exception("Data Wrong");
                    System.Diagnostics.Trace.Write("Data Wrong");
                //return;//调试直接return，以免阻碍后续读数
                {
                    byte CRCHi;
                    byte CRCLow;
                    CRC.CRC16(value, value.Length - 2, out CRCHi, out CRCLow);
                    if (CRCHi != value[value.Length - 2] && CRCLow != value[value.Length - 1])
                        System.Diagnostics.Trace.Write("CRC Wrong");
                    //{ throw new Exception("Data Wrong"); }

                }
            }
        }

        ChannelCategory IChannel.Category { get { return ChannelCategory.Device; } }
        List<byte[]> outlogs = new List<byte[]>();
        IList<byte[]> IChannel.OutLogs { get { return outlogs; } }
        List<byte[]> inlogs = new List<byte[]>();
        IList<byte[]> IChannel.InLogs { get { return inlogs; } }
        List<ICommWatch> Watchs = new List<ICommWatch>();
        void IChannel.AddWatch(ICommWatch watch)
        {
            Watchs.Add(watch);
        }
        void IChannel.RemoveWatch(ICommWatch watch)
        {
            Watchs.Remove(watch);
        }

        public override string ToString()
        {
            return this.DeviceName + ":" + this.Description + "(" +
                this.DeviceModel + " NCP:" + this.NCPAddress.ToString("X") + ")";
        }

        DeviceConfigBase config = new DeviceConfigBase();
        protected virtual DeviceConfigBase GetDeviceConfig()
        {
            return config;
        }

        protected virtual void SetDeviceConfig(DeviceConfigBase config)
        {
            this.config = config;
        }
        public class DeviceConfigBase{
            public DeviceConfigBase()
            {
                this.VoltageUnit = "V";
                this.CurrentUnit = "A";
            }

            public string Group { get; set; }
            public enum EnumActiveStandBy
            {
                None,
                Active,
                StandBy
            }

            public enum EnumDisplayCategory
            {
                PowerMeter,
                HighVoltageDevice
            }

            public EnumDisplayCategory DisplayCategory { get; set; }
            public EnumActiveStandBy ActiveStandBy { get; set; }

            public override string ToString()
            {
                string text = null;
                if (this.Group != null && this.Group.Length > 0)
                    text += this.Group + "/";
                switch (this.ActiveStandBy)
                {
                    case EnumActiveStandBy.None: break;
                    case EnumActiveStandBy.Active:text += "(主用)"; break;
                    case EnumActiveStandBy.StandBy: text += "(备用)"; break;
                }
                return text;
            }

            public string VoltageUnit{get;set;}
            public string CurrentUnit{get;set;} 
        }

        DeviceCounter Counter = new DeviceCounter();

        public class DeviceCounter
        {
            public int PowerRecordsCounter { get; set; }
            public int RespodesCounter { get; set; }
        }

    }
}
